package network

import (
	"fmt"
	"net"
	"strings"
	"sync"
	"time"
)

// Client 表示一个网络客户端
type Client struct {
	conn        net.Conn
	connType    string // "TCP" 或 "UDP"
	host        string
	port        string
	isConnected bool
	mutex       sync.RWMutex

	// 回调函数
	OnConnected    func()
	OnDisconnected func()
	OnDataReceived func(data []byte)
	OnError        func(err error)
}

// NewClient 创建新的客户端实例
func NewClient() *Client {
	return &Client{
		isConnected: false,
	}
}

// Connect 连接到服务器
func (c *Client) Connect(host, port, protocol string) error {
	c.mutex.Lock()
	defer c.mutex.Unlock()

	if c.isConnected {
		return fmt.Errorf("已经连接到服务器")
	}

	c.host = host
	c.port = port
	c.connType = strings.ToUpper(protocol)

	var err error

	switch c.connType {
	case "TCP":
		err = c.connectTCP()
	case "UDP":
		err = c.connectUDP()
	default:
		return fmt.Errorf("不支持的协议: %s", protocol)
	}

	if err != nil {
		if c.OnError != nil {
			c.OnError(err)
		}
		return err
	}

	c.isConnected = true

	if c.OnConnected != nil {
		c.OnConnected()
	}

	// 启动数据接收协程
	go c.receiveData()

	return nil
}

// connectTCP 建立TCP连接
func (c *Client) connectTCP() error {
	address := fmt.Sprintf("%s:%s", c.host, c.port)
	conn, err := net.DialTimeout("tcp", address, 10*time.Second)
	if err != nil {
		return fmt.Errorf("TCP连接失败: %v", err)
	}

	c.conn = conn
	return nil
}

// connectUDP 建立UDP连接
func (c *Client) connectUDP() error {
	address := fmt.Sprintf("%s:%s", c.host, c.port)
	conn, err := net.DialTimeout("udp", address, 10*time.Second)
	if err != nil {
		return fmt.Errorf("UDP连接失败: %v", err)
	}

	c.conn = conn
	return nil
}

// Disconnect 断开连接
func (c *Client) Disconnect() error {
	c.mutex.Lock()
	defer c.mutex.Unlock()

	if !c.isConnected || c.conn == nil {
		return nil
	}

	err := c.conn.Close()
	c.isConnected = false
	c.conn = nil

	if c.OnDisconnected != nil {
		c.OnDisconnected()
	}

	return err
}

// Send 发送数据
func (c *Client) Send(data []byte) error {
	c.mutex.RLock()
	defer c.mutex.RUnlock()

	if !c.isConnected || c.conn == nil {
		return fmt.Errorf("未连接到服务器")
	}

	_, err := c.conn.Write(data)
	if err != nil {
		if c.OnError != nil {
			c.OnError(err)
		}
		return fmt.Errorf("发送数据失败: %v", err)
	}

	return nil
}

// SendString 发送字符串数据
func (c *Client) SendString(data string) error {
	return c.Send([]byte(data))
}

// receiveData 接收数据的协程
func (c *Client) receiveData() {
	defer func() {
		if r := recover(); r != nil {
			if c.OnError != nil {
				c.OnError(fmt.Errorf("数据接收协程异常: %v", r))
			}
		}
	}()

	buffer := make([]byte, 4096)

	for c.isConnected {
		c.mutex.RLock()
		if c.conn == nil {
			c.mutex.RUnlock()
			break
		}

		// 设置读取超时
		err := c.conn.SetReadDeadline(time.Now().Add(1 * time.Second))
		if err != nil {
			c.mutex.RUnlock()
			if c.OnError != nil {
				c.OnError(err)
			}
			break
		}

		n, err := c.conn.Read(buffer)
		c.mutex.RUnlock()

		if err != nil {
			if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
				// 超时继续循环
				continue
			}

			// 只有在连接真正中断时才退出
			if c.OnError != nil {
				c.OnError(err)
			}

			// 检查连接是否真的断开了
			c.mutex.Lock()
			if c.isConnected && c.conn != nil {
				c.isConnected = false
				c.conn.Close()
				c.conn = nil
			}
			c.mutex.Unlock()
			break
		}

		if n > 0 && c.OnDataReceived != nil {
			data := make([]byte, n)
			copy(data, buffer[:n])
			c.OnDataReceived(data)
		}
	}

	// 只有在连接真正断开时才调用OnDisconnected
	c.mutex.RLock()
	wasConnected := c.isConnected
	c.mutex.RUnlock()

	if wasConnected && c.OnDisconnected != nil {
		c.OnDisconnected()
	}
}

// IsConnected 检查是否已连接
func (c *Client) IsConnected() bool {
	c.mutex.RLock()
	defer c.mutex.RUnlock()
	return c.isConnected
}

// GetConnectionInfo 获取连接信息
func (c *Client) GetConnectionInfo() (string, string, string) {
	c.mutex.RLock()
	defer c.mutex.RUnlock()
	return c.host, c.port, c.connType
}
